package juc.fulture;


import sun.misc.Unsafe;

import java.lang.invoke.MethodHandles;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.LockSupport;

/**
 * @description:
 * @author: zk
 * @date: 2023-12-15
 */
public class MyFutureTask<R> implements Runnable {
    private R outcome;
    private WaitNode head;
    private volatile WaitNode tail;
    private Callable<R> callable;
    private volatile int status;

    // 状态常量
    private static final int NEW = 0;
    private static final int COMPLETING = 1;
    private static final int NORMAL = 2;
    private static final int EXCEPTION = 3;

    public MyFutureTask(Callable<R> callable) {
        this.callable = callable;
        head = new WaitNode();
    }


    @Override
    public void run() {
        if (status != NEW) {
            return;
        }
        // 处理
        try {
            outcome = callable.call();
            status = NORMAL;
        } catch (Exception e) {
            outcome = null;
            status = EXCEPTION;
        } finally {
            finish();
        }
    }

    /**
     * 唤醒等待节点
     */
    private void finish() {
        WaitNode tail = head.next;
        while (tail != null) {
            Thread t = tail.thread;
            if (t != null) {
                LockSupport.unpark(t);
            }
            tail = tail.next;
        }
    }


    public R get() {
        if (status <= COMPLETING) {
            // 入队
            WaitNode node = enqueue();
            // 阻塞
            LockSupport.park(node.thread);
        }
        return outcome;
    }

    /**
     * cas 入队
     *
     * @return
     */
    private WaitNode enqueue() {
        WaitNode q = null;
        for (; ; ) {
            // 设置队头
            q = new WaitNode();
            WaitNode oldTail = tail;
            if (waitNodeCas(oldTail, q)) {
                if (oldTail == null) {
                    oldTail = head;
                }
                oldTail.next = tail;
                return q;
            }

        }
    }


    static final class WaitNode {
        private Thread thread;
        private WaitNode next;

        public WaitNode() {
            this.thread = Thread.currentThread();
        }
    }


    // ------------------cas相关------------------
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long stateOffset;
    private static final long tailOffset;


    static {
        MethodHandles.Lookup l = MethodHandles.lookup();
        try {
            stateOffset = unsafe.objectFieldOffset
                    (MyFutureTask.class.getDeclaredField("state"));
            tailOffset = unsafe.objectFieldOffset
                    (MyFutureTask.class.getDeclaredField("tail"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    protected boolean stateCas(int old, int newValue) {
        return unsafe.compareAndSwapInt(this, stateOffset, old, newValue);
    }

    private boolean waitNodeCas(MyFutureTask.WaitNode old, MyFutureTask.WaitNode newValue) {
        return unsafe.compareAndSwapObject(this, tailOffset, old, newValue);
    }


}
